home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************
- * TileStackWindows.c
- *
- * Set of routines to quickly rearrange windows
- * on multiple devices.
- *
- * Mike Scanlin 10 July 1993
- ****************************************************/
-
- #include <GestaltEqu.h>
- #include <Traps.h>
- #include "TileStackWindows.h"
-
- /*****************************************************
- * defines
- ****************************************************/
-
- #define BAD_DEVICE ((GDHandle) -1)
- #define TOPLEFT_SLOP 2
- #define BOTRIGHT_SLOP 3
- #define NIL 0L
-
- /* MAX_WINDOWS is not a real limit but stack space
- * requirements for TileStackWindows are equal to
- * (sizeof(WindowElement) * 2 * MAX_WINDOWS) so
- * don't make it too big. It's the max number of
- * windows that TileStackWindows can deal with.
- */
- #define MAX_WINDOWS 100
-
- /*****************************************************
- * typedefs
- ****************************************************/
-
- typedef pascal long (**WDefProcHndl)(int var,
- WindowPtr w, int message, long param);
-
- /*****************************************************
- * prototypes
- ****************************************************/
-
- static GDHandle DominantDevice(Rect *theRect);
-
- /*****************************************************
- * TileStackWindows
- *
- * Calls theTileStackProc on a per-device basis to
- * clean up (stack, tile or whatever else you can
- * think of) all the windows on that device. Once
- * all devices have been taken care of the part of
- * the screen that needs to be updated is updated.
- ****************************************************/
- void TileStackWindows(TileStackWindowsProc
- theTileStackProc)
- {
- WindowElementPtr p, dp;
- WindowPeek w;
- GDHandle deviceHndl;
- RgnHandle sumOfStructRgns;
- WindowElement theWindows[MAX_WINDOWS],
- theDeviceWindows[MAX_WINDOWS];
- long theQDVers;
- Rect enclosingRect;
- int i, totalWindows,
- windowsToClean,
- deviceWindows;
- Boolean needToRedraw, hasColorQD;
-
- /* check for color QuickDraw */
- hasColorQD = FALSE;
- if (TrapIsAvailable(_Gestalt)) {
- Gestalt(gestaltQuickdrawVersion, &theQDVers);
- hasColorQD = theQDVers >= 0x0100;
- }
-
- sumOfStructRgns = NewRgn();
- needToRedraw = FALSE;
-
- /* find the dominant device for each window
- * as we add it to our list of windows
- */
- p = theWindows;
- totalWindows = 0;
- w = (WindowPeek) FrontWindow();
- while (w != NIL && totalWindows < MAX_WINDOWS) {
- p->theWindowPtr = w;
- p->theDevHndl = NIL;
- if (hasColorQD)
- p->theDevHndl =
- DominantDevice(&(*w->strucRgn)->rgnBBox);
- p++;
- totalWindows++;
- /* or the old struct region into the
- * update region
- */
- UnionRgn(sumOfStructRgns, w->strucRgn,
- sumOfStructRgns);
- w = w->nextWindow;
- }
-
- if (totalWindows == 0)
- goto Exit;
-
- /* set up enclosingRect here in case we don't
- * have color QD; if we do have colorQD then
- * enclosingRect is set again in the loop below
- * on a per-device basis
- */
- enclosingRect = (*GetGrayRgn())->rgnBBox;
- enclosingRect.top += TOPLEFT_SLOP;
- enclosingRect.left += TOPLEFT_SLOP;
- enclosingRect.bottom -= BOTRIGHT_SLOP;
- enclosingRect.right -= BOTRIGHT_SLOP;
-
- windowsToClean = totalWindows;
- do {
- /* find the first device in the list that we
- * haven't already done and copy all elements
- * from that device into a new list
- */
- p = theWindows;
- dp = theDeviceWindows;
- deviceWindows = 0;
- deviceHndl = BAD_DEVICE;
- i = totalWindows;
- do {
- if (p->theDevHndl != BAD_DEVICE) {
- if (deviceHndl == BAD_DEVICE) {
- /* this is the first time we've
- * seen this device so we do a
- * little set up first
- */
- deviceHndl = p->theDevHndl;
- /* if we have colorQD, use the
- * device's rect
- */
- if (deviceHndl != NIL) {
- enclosingRect = (*deviceHndl)->gdRect;
- enclosingRect.top += TOPLEFT_SLOP;
- enclosingRect.left += TOPLEFT_SLOP;
- enclosingRect.bottom -= BOTRIGHT_SLOP;
- enclosingRect.right -= BOTRIGHT_SLOP;
- if (deviceHndl == GetMainDevice())
- enclosingRect.top += GetMBarHeight();
- }
- }
- if (deviceHndl == p->theDevHndl) {
- /* it's on the current device,
- * add it to the list
- */
- *dp++ = *p;
- deviceWindows++;
- /* we don't want to see this
- * one again
- */
- p->theDevHndl = BAD_DEVICE;
- }
- }
- p++;
- } while (--i);
-
- if (deviceWindows > 0) {
- /* do something to the windows on
- * this device
- */
- needToRedraw |= (*theTileStackProc)
- (&enclosingRect, theDeviceWindows,
- deviceWindows);
- windowsToClean -= deviceWindows;
- }
-
- } while (windowsToClean > 0);
-
- if (needToRedraw) {
-
- /* add all of the new struct regions to the
- * update region
- */
- p = theWindows;
- do {
- UnionRgn(sumOfStructRgns,
- p->theWindowPtr->strucRgn,
- sumOfStructRgns);
- p++;
- } while (--totalWindows);
-
- /* To see a cool effect, trap on the next
- * instruction and watch the screen as you
- * step over it. All window frames are drawn
- * with this one call to the ROMs.
- */
- PaintBehind(theWindows[0].theWindowPtr,
- sumOfStructRgns);
-
- /* Need to reset the visRgns since
- * MySizeWindow nuked 'em.
- */
- CalcVisBehind(theWindows[0].theWindowPtr,
- sumOfStructRgns);
- }
-
- Exit:
-
- DisposeRgn(sumOfStructRgns);
- }
-
-
- /*****************************************************
- * DominantDevice
- *
- * This returns a device hndl to the device that
- * owns most of the given Rect (which is in global
- * coordinates). This routine requires ColorQD.
- ****************************************************/
- static GDHandle DominantDevice(Rect *theRect)
- {
- GDHandle nthDevice, theDevice;
- long greatestArea, sectArea;
- Rect theSect;
-
- nthDevice = theDevice = GetDeviceList();
- greatestArea = 0;
- do {
- if (TestDeviceAttribute(nthDevice, screenDevice) &&
- TestDeviceAttribute(nthDevice, screenActive)) {
- SectRect(theRect, &(*nthDevice)->gdRect,
- &theSect);
- sectArea =
- ((long) (theSect.bottom - theSect.top)) *
- ((long) (theSect.right - theSect.left));
- if (sectArea > greatestArea) {
- greatestArea = sectArea;
- theDevice = nthDevice;
- }
- }
- nthDevice = GetNextDevice(nthDevice);
- } while (nthDevice != NIL);
-
- return (theDevice);
- }
-
-
- /*****************************************************
- * MyMoveWindow
- *
- * Quickly move the window. No screen updating
- * will take place.
- ****************************************************/
- Boolean MyMoveWindow(WindowPtr w, int leftGlobal,
- int topGlobal, Boolean sizeChanged)
- {
- Handle theDefProc;
- GrafPtr oldPort;
- Point upperLeft;
- char oldState;
- Boolean itMoved;
-
- itMoved = FALSE;
-
- oldPort = thePort;
- SetPort(w);
-
- /* Don't move it if it's already there, unless
- * it was just resized (in which case we don't
- * really need to call MovePortTo but we do
- * need to call the windowDefProc below to fix
- * up the regions).
- */
- if (!sizeChanged) {
- upperLeft = topLeft(w->portRect);
- LocalToGlobal(&upperLeft);
- if (upperLeft.h == leftGlobal &&
- upperLeft.v == topGlobal)
- goto Exit;
- }
-
- itMoved = TRUE;
-
- MovePortTo(leftGlobal, topGlobal);
-
- theDefProc = ((WindowPeek) w)->windowDefProc;
- oldState = HGetState(theDefProc);
- HLock(theDefProc);
-
- /* call the WDEF to update the regions */
- (*(WDefProcHndl) theDefProc)(zoomDocProc, w,
- wCalcRgns, 0);
-
- HSetState(theDefProc, oldState);
-
- Exit:
-
- SetPort(oldPort);
-
- return (itMoved);
- }
-
-
- /*****************************************************
- * MySizeWindow
- *
- * Quickly set the size of a window. Set the
- * visRgn to NIL so that no screen updating takes
- * place. The visRgn will be reset when we call
- * CalcVisBehind later.
- ****************************************************/
- Boolean MySizeWindow(WindowPtr w, int width,
- int height)
- {
- GrafPtr oldPort;
-
- /* don't size it if it's already the right size */
- if (w->portRect.right - w->portRect.left == width &&
- w->portRect.bottom - w->portRect.top == height)
- return(FALSE);
-
- oldPort = thePort;
- SetPort(w);
-
- PortSize(width, height);
-
- /* nuke the visRgn so that moving this port
- * (in MyMoveWindow) won't cause any screen
- * drawing
- */
- SetEmptyRgn(((GrafPtr) w)->visRgn);
-
- SetPort(oldPort);
-
- return(TRUE);
- }
-